home *** CD-ROM | disk | FTP | other *** search
/ Risc World 5 / Risc World 5.iso / SOFTWARE / Issue3 / Games / xrick / !xrick / src / c / sysvid < prev    next >
Text File  |  2004-06-28  |  9KB  |  390 lines

  1. /*
  2.  * xrick/src/sysvid.c
  3.  *
  4.  * Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved.
  5.  *
  6.  * The use and distribution terms for this software are contained in the file
  7.  * named README, which can be found in the root of this distribution. By
  8.  * using this software in any fashion, you are agreeing to be bound by the
  9.  * terms of this license.
  10.  *
  11.  * You must not remove this notice, or any other, from this software.
  12.  */
  13.  
  14. #include <stdlib.h> /* malloc */
  15.  
  16. #include <SDL.h>
  17.  
  18. #include "system.h"
  19. #include "game.h"
  20. #include "img.h"
  21. #include "debug.h"
  22.  
  23. #ifdef __MSVC__
  24. #include <memory.h> /* memset */
  25. #endif
  26.  
  27. U8 *sysvid_fb; /* frame buffer */
  28. rect_t SCREENRECT = {0, 0, SYSVID_WIDTH, SYSVID_HEIGHT, NULL}; /* whole fb */
  29.  
  30. static SDL_Color palette[256];
  31. static SDL_Surface *screen;
  32. static U32 videoFlags;
  33.  
  34. static U8 zoom = SYSVID_ZOOM; /* actual zoom level */
  35. static U8 szoom = 0;  /* saved zoom level */
  36. static U8 fszoom = 0;  /* fullscreen zoom level */
  37.  
  38. #include "img_icon.e"
  39.  
  40. /*
  41.  * color tables
  42.  */
  43.  
  44. #ifdef GFXPC
  45. static U8 RED[] = { 0x00, 0x50, 0xf0, 0xf0, 0x00, 0x50, 0xf0, 0xf0 };
  46. static U8 GREEN[] = { 0x00, 0xf8, 0x50, 0xf8, 0x00, 0xf8, 0x50, 0xf8 };
  47. static U8 BLUE[] = { 0x00, 0x50, 0x50, 0x50, 0x00, 0xf8, 0xf8, 0xf8 };
  48. #endif
  49. #ifdef GFXST
  50. static U8 RED[] = { 0x00, 0xd8, 0xb0, 0xf8,
  51.                     0x20, 0x00, 0x00, 0x20,
  52.                     0x48, 0x48, 0x90, 0xd8,
  53.                     0x48, 0x68, 0x90, 0xb0,
  54.                     /* cheat colors */
  55.                     0x50, 0xe0, 0xc8, 0xf8,
  56.                     0x68, 0x50, 0x50, 0x68,
  57.                     0x80, 0x80, 0xb0, 0xe0,
  58.                     0x80, 0x98, 0xb0, 0xc8
  59. };
  60. static U8 GREEN[] = { 0x00, 0x00, 0x6c, 0x90,
  61.                       0x24, 0x48, 0x6c, 0x48,
  62.                       0x6c, 0x24, 0x48, 0x6c,
  63.                       0x48, 0x6c, 0x90, 0xb4,
  64.               /* cheat colors */
  65.                       0x54, 0x54, 0x9c, 0xb4,
  66.                       0x6c, 0x84, 0x9c, 0x84,
  67.                       0x9c, 0x6c, 0x84, 0x9c,
  68.                       0x84, 0x9c, 0xb4, 0xcc
  69. };
  70. static U8 BLUE[] = { 0x00, 0x00, 0x68, 0x68,
  71.                      0x20, 0xb0, 0xd8, 0x00,
  72.                      0x20, 0x00, 0x00, 0x00,
  73.                      0x48, 0x68, 0x90, 0xb0,
  74.              /* cheat colors */
  75.                      0x50, 0x50, 0x98, 0x98,
  76.                      0x68, 0xc8, 0xe0, 0x50,
  77.                      0x68, 0x50, 0x50, 0x50,
  78.                      0x80, 0x98, 0xb0, 0xc8};
  79. #endif
  80.  
  81. /*
  82.  * Initialize screen
  83.  */
  84. static
  85. SDL_Surface *initScreen(U16 w, U16 h, U8 bpp, U32 flags)
  86. {
  87.   return SDL_SetVideoMode(w, h, bpp, flags);
  88. }
  89.  
  90. void
  91. sysvid_setPalette(img_color_t *pal, U16 n)
  92. {
  93.   U16 i;
  94.  
  95.   for (i = 0; i < n; i++) {
  96.     palette[i].r = pal[i].r;
  97.     palette[i].g = pal[i].g;
  98.     palette[i].b = pal[i].b;
  99.   }
  100.   SDL_SetColors(screen, (SDL_Color *)&palette, 0, n);
  101. }
  102.  
  103. void
  104. sysvid_restorePalette()
  105. {
  106.   SDL_SetColors(screen, (SDL_Color *)&palette, 0, 256);
  107. }
  108.  
  109. void
  110. sysvid_setGamePalette()
  111. {
  112.   U8 i;
  113.   img_color_t pal[256];
  114.  
  115.   for (i = 0; i < 32; ++i) {
  116.     pal[i].r = RED[i];
  117.     pal[i].g = GREEN[i];
  118.     pal[i].b = BLUE[i];
  119.   }
  120.   sysvid_setPalette(pal, 32);
  121. }
  122.  
  123. /*
  124.  * Initialize video modes
  125.  */
  126. void
  127. sysvid_chkvm(void)
  128. {
  129.   SDL_Rect **modes;
  130.   U8 i, mode = 0;
  131.  
  132.   IFDEBUG_VIDEO(sys_printf("xrick/video: checking video modes\n"););
  133.  
  134.   modes = SDL_ListModes(NULL, videoFlags|SDL_FULLSCREEN);
  135.  
  136.   if (modes == (SDL_Rect **)0)
  137.     sys_panic("xrick/video: SDL can not find an appropriate video mode\n");
  138.  
  139.   if (modes == (SDL_Rect **)-1) {
  140.     /* can do what you want, everything is possible */
  141.     IFDEBUG_VIDEO(sys_printf("xrick/video: SDL says any video mode is OK\n"););
  142.     fszoom = 1;
  143.   }
  144.   else {
  145.     IFDEBUG_VIDEO(sys_printf("xrick/video: SDL says, use these modes:\n"););
  146.     for (i = 0; modes[i]; i++) {
  147.       IFDEBUG_VIDEO(sys_printf("  %dx%d\n", modes[i]->w, modes[i]->h););
  148.       if (modes[i]->w <= modes[mode]->w && modes[i]->w >= SYSVID_WIDTH &&
  149.       modes[i]->h * SYSVID_WIDTH >= modes[i]->w * SYSVID_HEIGHT) {
  150.     mode = i;
  151.     fszoom = modes[mode]->w / SYSVID_WIDTH;
  152.       }
  153.     }
  154.     if (fszoom != 0) {
  155.       IFDEBUG_VIDEO(
  156.         sys_printf("xrick/video: fullscreen at %dx%d w/zoom=%d\n",
  157.            modes[mode]->w, modes[mode]->h, fszoom);
  158.     );
  159.     }
  160.     else {
  161.       IFDEBUG_VIDEO(
  162.         sys_printf("xrick/video: can not compute fullscreen zoom, use 1\n");
  163.     );
  164.       fszoom = 1;
  165.     }
  166.   }
  167. }
  168.  
  169. /*
  170.  * Initialise video
  171.  */
  172. void
  173. sysvid_init(void)
  174. {
  175.   SDL_Surface *s;
  176.   U8 *mask, tpix;
  177.   U32 len, i;
  178.  
  179.   IFDEBUG_VIDEO(printf("xrick/video: start\n"););
  180.  
  181.   /* SDL */
  182.   if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) < 0)
  183.     sys_panic("xrick/video: could not init SDL\n");
  184.  
  185.   /* various WM stuff */
  186.   SDL_WM_SetCaption("xrick", "xrick");
  187.   SDL_ShowCursor(SDL_DISABLE);
  188.   s = SDL_CreateRGBSurfaceFrom(IMG_ICON->pixels, IMG_ICON->w, IMG_ICON->h, 8, IMG_ICON->w, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
  189.   SDL_SetColors(s, (SDL_Color *)IMG_ICON->colors, 0, IMG_ICON->ncolors);
  190.  
  191.   tpix = *(IMG_ICON->pixels);
  192.   IFDEBUG_VIDEO(
  193.     sys_printf("xrick/video: icon is %dx%d\n",
  194.            IMG_ICON->w, IMG_ICON->h);
  195.     sys_printf("xrick/video: icon transp. color is #%d (%d,%d,%d)\n", tpix,
  196.            IMG_ICON->colors[tpix].r,
  197.            IMG_ICON->colors[tpix].g,
  198.            IMG_ICON->colors[tpix].b);
  199.     );
  200.     /*
  201.  
  202.     * old dirty stuff to implement transparency. SetColorKey does it
  203.     * on Windows w/out problems. Linux? FIXME!
  204.  
  205.   len = IMG_ICON->w * IMG_ICON->h;
  206.   mask = (U8 *)malloc(len/8);
  207.   memset(mask, 0, len/8);
  208.   for (i = 0; i < len; i++)
  209.     if (IMG_ICON->pixels[i] != tpix) mask[i/8] |= (0x80 >> (i%8));
  210.     */
  211.   /*
  212.    * FIXME
  213.    * Setting a mask produces strange results depending on the
  214.    * Window Manager. On fvwm2 it is shifted to the right ...
  215.    */
  216.   /*SDL_WM_SetIcon(s, mask);*/
  217.     SDL_SetColorKey(s,
  218.                     SDL_SRCCOLORKEY,
  219.                     SDL_MapRGB(s->format,IMG_ICON->colors[tpix].r,IMG_ICON->colors[tpix].g,IMG_ICON->colors[tpix].b));
  220.  
  221.   SDL_WM_SetIcon(s, NULL);
  222.  
  223.   /* video modes and screen */
  224.   videoFlags = SDL_HWSURFACE|SDL_HWPALETTE;
  225.   sysvid_chkvm();  /* check video modes */
  226.   if (sysarg_args_zoom)
  227.     zoom = sysarg_args_zoom;
  228.   if (sysarg_args_fullscreen) {
  229.     videoFlags |= SDL_FULLSCREEN;
  230.     szoom = zoom;
  231.     zoom = fszoom;
  232.   }
  233.   screen = initScreen(SYSVID_WIDTH * zoom,
  234.               SYSVID_HEIGHT * zoom,
  235.               8, videoFlags);
  236.  
  237.   /*
  238.    * create v_ frame buffer
  239.    */
  240.   sysvid_fb = malloc(SYSVID_WIDTH * SYSVID_HEIGHT);
  241.   if (!sysvid_fb)
  242.     sys_panic("xrick/video: sysvid_fb malloc failed\n");
  243.  
  244.   IFDEBUG_VIDEO(printf("xrick/video: ready\n"););
  245. }
  246.  
  247. /*
  248.  * Shutdown video
  249.  */
  250. void
  251. sysvid_shutdown(void)
  252. {
  253.   free(sysvid_fb);
  254.   sysvid_fb = NULL;
  255.  
  256.   SDL_Quit();
  257. }
  258.  
  259. /*
  260.  * Update screen
  261.  * NOTE errors processing ?
  262.  */
  263. void
  264. sysvid_update(rect_t *rects)
  265. {
  266.   static SDL_Rect area;
  267.   U16 x, y, xz, yz;
  268.   U8 *p, *q, *p0, *q0;
  269.  
  270.   if (rects == NULL)
  271.     return;
  272.  
  273.   if (SDL_LockSurface(screen) == -1)
  274.     sys_panic("xrick/panic: SDL_LockSurface failed\n");
  275.  
  276.   while (rects) {
  277.     p0 = sysvid_fb;
  278.     p0 += rects->x + rects->y * SYSVID_WIDTH;
  279.     q0 = (U8 *)screen->pixels;
  280. #ifdef __riscos__
  281.     q0 += (rects->x + rects->y * screen->pitch) * zoom;
  282. #else
  283.     q0 += (rects->x + rects->y * SYSVID_WIDTH * zoom) * zoom;
  284. #endif
  285.  
  286.     for (y = rects->y; y < rects->y + rects->height; y++) {
  287.       for (yz = 0; yz < zoom; yz++) {
  288.     p = p0;
  289.     q = q0;
  290.     for (x = rects->x; x < rects->x + rects->width; x++) {
  291.       for (xz = 0; xz < zoom; xz++) {
  292.         *q = *p;
  293.         q++;
  294.       }
  295.       p++;
  296.     }
  297. #ifdef __riscos__
  298.         q0 += screen->pitch;
  299. #else
  300.     q0 += SYSVID_WIDTH * zoom;
  301. #endif
  302.       }
  303.       p0 += SYSVID_WIDTH;
  304.     }
  305.  
  306.     IFDEBUG_VIDEO2(
  307.     for (y = rects->y; y < rects->y + rects->height; y++)
  308.       for (yz = 0; yz < zoom; yz++) {
  309.     p = (U8 *)screen->pixels + rects->x * zoom + (y * zoom + yz) * SYSVID_WIDTH * zoom;
  310.     *p = 0x01;
  311.     *(p + rects->width * zoom - 1) = 0x01;
  312.       }
  313.  
  314.     for (x = rects->x; x < rects->x + rects->width; x++)
  315.       for (xz = 0; xz < zoom; xz++) {
  316.     p = (U8 *)screen->pixels + x * zoom + xz + rects->y * zoom * SYSVID_WIDTH * zoom;
  317.     *p = 0x01;
  318.     *(p + ((rects->height * zoom - 1) * zoom) * SYSVID_WIDTH) = 0x01;
  319.       }
  320.     );
  321.  
  322.     area.x = rects->x * zoom;
  323.     area.y = rects->y * zoom;
  324.     area.h = rects->height * zoom;
  325.     area.w = rects->width * zoom;
  326.     SDL_UpdateRects(screen, 1, &area);
  327.  
  328.     rects = rects->next;
  329.   }
  330.  
  331.   SDL_UnlockSurface(screen);
  332. }
  333.  
  334.  
  335. /*
  336.  * Clear screen
  337.  * (077C)
  338.  */
  339. void
  340. sysvid_clear(void)
  341. {
  342.   memset(sysvid_fb, 0, SYSVID_WIDTH * SYSVID_HEIGHT);
  343. }
  344.  
  345.  
  346. /*
  347.  * Zoom
  348.  */
  349. void
  350. sysvid_zoom(S8 z)
  351. {
  352.   if (!(videoFlags & SDL_FULLSCREEN) &&
  353.       ((z < 0 && zoom > 1) ||
  354.        (z > 0 && zoom < SYSVID_MAXZOOM))) {
  355.     zoom += z;
  356.     screen = initScreen(SYSVID_WIDTH * zoom,
  357.             SYSVID_HEIGHT * zoom,
  358.             screen->format->BitsPerPixel, videoFlags);
  359.     sysvid_restorePalette();
  360.     sysvid_update(&SCREENRECT);
  361.   }
  362. }
  363.  
  364. /*
  365.  * Toggle fullscreen
  366.  */
  367. void
  368. sysvid_toggleFullscreen(void)
  369. {
  370.   videoFlags ^= SDL_FULLSCREEN;
  371.  
  372.   if (videoFlags & SDL_FULLSCREEN) {  /* go fullscreen */
  373.     szoom = zoom;
  374.     zoom = fszoom;
  375.   }
  376.   else {  /* go window */
  377.     zoom = szoom;
  378.   }
  379.   screen = initScreen(SYSVID_WIDTH * zoom,
  380.               SYSVID_HEIGHT * zoom,
  381.               screen->format->BitsPerPixel, videoFlags);
  382.   sysvid_restorePalette();
  383.   sysvid_update(&SCREENRECT);
  384. }
  385.  
  386. /* eof */
  387.  
  388.  
  389.  
  390.